/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.adama.controller;

import fr.adama.dto.AdherentDTO;
import fr.adama.dto.BulletinPaieDTO;
import fr.adama.dto.ContratDTO;
import fr.adama.dto.EmployeDTO;
import fr.adama.dto.notModel.SearchBulletin;
import fr.adama.entite.BulletinPaie;
import fr.adama.entite.Contrat;
import fr.adama.entite.typePerso.EtatBulletin;
import fr.adama.service.AdherentService;
import fr.adama.service.BulletinPaieService;
import fr.adama.service.ContratService;
import fr.adama.service.EmployeService;
import fr.adama.util.DateFormatFactory;
import fr.adama.validator.BulletinPaieValidator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.validation.Valid;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 *
 * @author avisto
 */
@Controller
public class BulletinPaieController {

    private static final Logger logger = LoggerFactory.getLogger(BulletinPaieController.class);
    @Autowired
    BulletinPaieService bulletinPaieService;
    @Autowired
    ContratService contratService;
    @Autowired
    EmployeService employeService;
    @Autowired
    AdherentService adhernetService;
    @Autowired
    private MessageSource messageSource;

    @RequestMapping("/bulletin/index.do")
    public ModelAndView index() {
        return new ModelAndView("bulletin/index");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/add.do")
    public ModelAndView add(@RequestParam(value = "idContrat", required = false) Long idContrat) {
        Map<String, Object> map = new HashMap<>();
        BulletinPaieDTO bulletin = new BulletinPaieDTO();
        map.put("bulletin", bulletin);
        if (idContrat != null) {
            ContratDTO contrat = contratService.getById(idContrat, Contrat.class, ContratDTO.class);
            map.put("contrat", contrat);
            return new ModelAndView("bulletin/add", map);
        }
        return new ModelAndView("bulletin/addWithSearch", map);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/bulletin/add.do")
    public ModelAndView insertModelPaie(@Valid @ModelAttribute("bulletin") BulletinPaieDTO bulletin, BindingResult result, RedirectAttributes redirectAttributes, Locale locale) {

        result = new BeanPropertyBindingResult(bulletin, "bulletin");

        BulletinPaieValidator validator = new BulletinPaieValidator(messageSource);
        validator.validate(bulletin, result);

        if (result.hasErrors()) {
            Map<String, Object> map = new HashMap<>();
            map.put("bulletin", bulletin);
            ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
            map.put("contrat", contrat);
            map.put("org.springframework.validation.BindingResult.bulletin", result);
            return new ModelAndView("bulletin/add", map);
        }

        try {
            logger.info("Ajout d'un bulletin de paie pour le contrat.id={}", bulletin.getContrat().getId());
            bulletin = bulletinPaieService.addBulletinPaie(bulletin);
        } catch (DataIntegrityViolationException ex) {
            logger.error("Erreur d'ajout d'un bulletin de paie pour le contrat.id={}", bulletin.getContrat().getId(), ex);
            if (ex.getCause() instanceof ConstraintViolationException) {
                ConstraintViolationException cdts = (ConstraintViolationException) ex.getCause();
                if (cdts.getConstraintName().equalsIgnoreCase("BULLETINEXIST")) {
                    Map<String, Object> map = new HashMap<>();
                    ObjectError error = new ObjectError("periode", messageSource.getMessage("Bulletin.add.error.bulletin.exist", new String[]{DateFormatFactory.getDateFormatPeriode().format(bulletin.getPeriode())}, new Locale("fr")));
                    result.addError(error);
                    map.put("bulletin", bulletin);
                    ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
                    map.put("contrat", contrat);
                    map.put("org.springframework.validation.BindingResult.bulletin", result);
                    return new ModelAndView("bulletin/add", map);
                }

            }
        }

        return new ModelAndView("redirect:/bulletin/show.do", "id", bulletin.getId());
    }

    @RequestMapping(value = "/bulletin/searchContrat.do", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<ContratDTO> searchEmploye(@RequestParam(required = true, value = "field") String field) {

        EmployeDTO employe = new EmployeDTO();
        employe.setNom(field);
        AdherentDTO adherent = new AdherentDTO();
        adherent.setNomPrenom(field);
        List<ContratDTO> result = new ArrayList<>();
        for (EmployeDTO temp : employeService.searchByEntity(employe)) {
            result.addAll(temp.getContrats());
        }
        for (AdherentDTO temp : adhernetService.searchByEntity(adherent)) {
            result.addAll(temp.getContrats());
        }
        return result;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/show.do")
    public ModelAndView show(@RequestParam(required = true, value = "id") Long id) {
        BulletinPaieDTO bulletin = bulletinPaieService.getById(id, BulletinPaie.class, BulletinPaieDTO.class);

        return new ModelAndView("bulletin/show", "bulletin", bulletin);
    }

    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/update.do")
    public ModelAndView update(@RequestParam(required = true, value = "id") Long id) {
        BulletinPaieDTO bulletin = bulletinPaieService.getById(id, BulletinPaie.class, BulletinPaieDTO.class);
        Map<String, Object> map = new HashMap<>();
        map.put("bulletin", bulletin);
        ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
        map.put("contrat", contrat);
        return new ModelAndView("bulletin/update", map);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/bulletin/update.do")
    public ModelAndView modifier(@Valid @ModelAttribute("bulletin") BulletinPaieDTO bulletin, BindingResult result, RedirectAttributes redirectAttributes, Locale locale) {
        result = new BeanPropertyBindingResult(bulletin, "bulletin");

        BulletinPaieValidator validator = new BulletinPaieValidator(messageSource);
        validator.validate(bulletin, result);

        if (result.hasErrors()) {
            Map<String, Object> map = new HashMap<>();
            map.put("bulletin", bulletin);
            ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
            map.put("contrat", contrat);
            map.put("org.springframework.validation.BindingResult.bulletin", result);
            return new ModelAndView("bulletin/update", map);
        }
        if (bulletin.getEtatBulletin() == EtatBulletin.declare) {
            Map<String, Object> map = new HashMap<>();
            ObjectError error = new ObjectError("periode", messageSource.getMessage("Bulletin.update.error.bulletin.etat", new String[]{bulletin.getEtatBulletin().toString()}, new Locale("fr")));
            result.addError(error);
            map.put("bulletin", bulletin);
            ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
            map.put("contrat", contrat);
            map.put("org.springframework.validation.BindingResult.bulletin", result);
            return new ModelAndView("bulletin/update", map);
        }
        try {
            logger.info("Mis à jour du buleltin id={}", bulletin.getId());

            bulletin = bulletinPaieService.updateBulletinPaie(bulletin);
        } catch (DataIntegrityViolationException ex) {
            logger.error("Erreur de mis à jour du buleltin id={}", bulletin.getId(), ex);

            if (ex.getCause() instanceof ConstraintViolationException) {
                ConstraintViolationException cdts = (ConstraintViolationException) ex.getCause();
                if (cdts.getConstraintName().equalsIgnoreCase("BULLETINEXIST")) {
                    Map<String, Object> map = new HashMap<>();
                    ObjectError error = new ObjectError("periode", messageSource.getMessage("Bulletin.add.error.bulletin.exist", new String[]{DateFormatFactory.getDateFormatPeriode().format(bulletin.getPeriode())}, new Locale("fr")));
                    result.addError(error);
                    map.put("bulletin", bulletin);
                    ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);
                    map.put("contrat", contrat);
                    map.put("org.springframework.validation.BindingResult.bulletin", result);
                    return new ModelAndView("bulletin/update", map);
                }

            }
        }

        return new ModelAndView("redirect:/bulletin/show.do", "id", bulletin.getId());
    }

    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/delete.do")
    public ModelAndView delete(@RequestParam(required = true, value = "id") Long id, RedirectAttributes redirectAttributes) {
        BulletinPaieDTO bulletin = bulletinPaieService.getById(id, BulletinPaie.class, BulletinPaieDTO.class);
        if (bulletin.getEtatBulletin() != EtatBulletin.saisi) {
            redirectAttributes.addFlashAttribute("ERROR_MESSAGE", messageSource.getMessage("Bulletin.delete.error", new String[]{""}, new Locale("fr")));

            return new ModelAndView("redirect:/bulletin/show.do", "id", bulletin.getId());
        }
        bulletinPaieService.delete(bulletin, BulletinPaie.class);
        redirectAttributes.addFlashAttribute("SUCCESS_MESSAGE", messageSource.getMessage("Bulletin.delete.success", new String[]{""}, new Locale("fr")));

        return new ModelAndView("redirect:/bulletin/index.do");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/search.do")
    public String searchPage(ModelMap model ) {
        SearchBulletin searchBulletin = new SearchBulletin();
        model.addAttribute("searchBulletin", searchBulletin);
        return "bulletin/search";
    }

    @RequestMapping(method = RequestMethod.POST, value = "/bulletin/search.do")
    public ModelAndView search(@ModelAttribute("searchBulletin") SearchBulletin searchBulletin) {
        
        List<BulletinPaieDTO> listBulletin=bulletinPaieService.searchBulletin(searchBulletin);
      
        return new ModelAndView("bulletin/search","listBulletin",listBulletin);
    }
    @RequestMapping(method = RequestMethod.GET, value = "/bulletin/print.do")
    public String printPage() {
        
        return "bulletin/print";
    }
}
